package utils

import (
	"context"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"github.com/smallnest/rpcx/share"
	"github.com/spf13/cast"
	"math/rand"
	"reflect"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

func Int64sContain(a []int64, x int64) bool {
	for _, v := range a {
		if v == x {
			return true
		}
	}
	return false
}

// 获取 uuid
func GenUUID() string {
	id := uuid.New()
	pass := hex.EncodeToString(id[:])
	tt := strconv.FormatInt(time.Now().Unix(), 10)
	return MultiJoinString("rpc", pass, tt)
}

// 获取函数名称
func GetFunctionName(i interface{}, seps ...rune) string {
	fn := runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()

	// 用 seps 进行分割
	fields := strings.FieldsFunc(fn, func(sep rune) bool {
		for _, s := range seps {
			if sep == s {
				return true
			}
		}
		return false
	})

	if size := len(fields); size > 0 {
		return fields[size-1]
	}
	return ""
}

/*
  获取随机数
  不传参：0-100
  传1个参数：0-指定参数
  传2个参数：第1个参数-第2个参数
*/

func RandNum(num ...int) int {
	var start, end int
	if len(num) == 0 {
		start = 0
		end = 100
	} else if len(num) == 1 {
		start = 0
		end = num[0]
	} else {
		start = num[0]
		end = num[1]
	}

	rRandNumUtils := rand.New(rand.NewSource(time.Now().UnixNano()))
	return rRandNumUtils.Intn(end-start+1) + start
}

const HandlerName = "handlerName"

func GetHandler(ctx context.Context) (handler string) {
	if ctx != nil {
		if ginCtx, ok := ctx.(*gin.Context); ok {
			handler = ginCtx.HandlerName()
		} else if rpcxCtx, ok := ctx.(*share.Context); ok {
			if v := rpcxCtx.Value(HandlerName); v != nil {
				if h, ok := v.(string); ok {
					handler = h
				}
			}
		}
	}
	return handler
}

func JoinArgs(showByte int, args ...interface{}) string {
	cnt := len(args)
	f := "%v"
	for cnt > 1 {
		f += " %v"
	}

	argVal := fmt.Sprintf(f, args...)

	l := len(argVal)
	if l > showByte {
		l = showByte
		argVal = argVal[:l] + " ..."
	}
	return argVal
}

func GetLocalServerID() (string, error) {
	CompanyName := "anxinsec"
	macAddr, err := GetMacAddr()
	if err != nil {
		return "", err
	}
	flagMD5 := md5.Sum([]byte(CompanyName + macAddr))
	localServerID := hex.EncodeToString(flagMD5[:])
	return localServerID, nil
}

func Int64SliceToString(s []int64, sepF ...string) string {
	if len(s) == 0 {
		return ""
	}
	var ss []string
	for _, v := range s {
		ss = append(ss, cast.ToString(v))
	}
	sep := ","
	if len(sepF) > 0 {
		sep = sepF[0]
	}
	return strings.Join(ss, sep)
}
